#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/spi/spidev.h>
 #define dev_name "CH390"
typedef enum
{
	SPIMODE0  =   SPI_MODE_0,
	SPIMODE1  =   SPI_MODE_1,
	SPIMODE2  =   SPI_MODE_2,
	SPIMODE3  =   SPI_MODE_3,
}SPI_MODE;
 
typedef enum
{
	S_6_75M  	=   6750000,
	S_13_5M  	=   13500000,
	S_27M  		=   27000000,
}SPI_SPEED;
 
int fd_spi = -1;
 
static int spi_init(void)
{
    SPI_MODE mode;
    char spi_bits;
    SPI_SPEED spi_speed;
    int ret;
 
    if(fd_spi > 0)
    {
        printf("spi is already init");
        return -1;
    }
 
    fd_spi = open("/dev/spidev1.0", O_RDWR);  //open spi设备/dev/spidev0.0
    if (fd_spi < 0)
    {
        printf("can't open spi dev %s, fd_spi = %d\n", dev_name, fd_spi);
        return -1;  
    }
 
    /*
    * spi mode
    */
    mode = SPIMODE3;
    ret = ioctl(fd_spi, SPI_IOC_WR_MODE32, &mode);//设置spi的模式
    if (ret == -1)
    {
        perror("can't set spi mode");
        close(fd_spi);
        return ret;
    }
    /*
     * bits per word
     */
    spi_bits = 8;
    ret = ioctl(fd_spi, SPI_IOC_WR_BITS_PER_WORD, &spi_bits);//设置spi的字长
    if (ret == -1)
    {
        perror("can't set bits per word");
        close(fd_spi);
        return ret;
    }
 
    /*
    * speed
    */
    spi_speed = (int)S_13_5M;
    ret = ioctl(fd_spi, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed);//设置spi的最大传输速率
    if (ret == -1)
    {
        perror("can't set max speed hz");
        close(fd_spi);
        return ret;
    }
    printf("spi mode:0x%x\n", mode);
    printf("bits per word: %d\n", spi_bits);
    printf("max speed    : %d Hz (%d KHz)\n", spi_speed, spi_speed/1000);
    printf("Successfully to init ipi %s, fd_spi = %d\n", dev_name, fd_spi);
    return fd_spi;
}
 
static int spi_uninit(void)
{
    int ret;
 
    ret = close(fd_spi);//关闭spi设备
    if (0 != ret)
    {
        printf("Failed to uninit i2c, ret = %d\n", ret);
    }      
    else
    {
        fd_spi = -1;
        printf("Successfully to uninit i2c, ret = %d\n", ret); 
    }
        
    return 0;
}
 
 
static void spi_read(void)
{
    int ret;
	int i;
    int len = 1024;
	char  readbuf[1024] = {0};
    
    ret = read(fd_spi, readbuf, len);//spi读操作
    if (ret < 0)
    {
        perror("can't read spi message");
        return ret;
    }
 
    for (i = 0; i<1024; i++) {
		if (!(i % 32))
		puts("");
		printf("%.2X ", readbuf[i]);
	}
	puts("");
 
    return 0;
}
 
 
static void spi_write(void)
{
    int ret;
	int i;
    int len = 1024;
	char  writebuf[1024];
    while(1) {
        for(i = 0 ;i < 1024;i++)
    {
        writebuf[i] = i%256;
    }
    
    ret = write(fd_spi, writebuf, len);//spi写操作
    if (ret < 0)
    {
        perror("can't write spi message");
        return ret;
    }
   // msleep(1);
    }
    
    return 0;
}
 
static void spi_write_read(void)//spi边写边读，全双工通信
{
    int ret;
	int i;
    int len = 1024;
	char  writebuf[1024];
	char  readbuf[1024] = {0};
    
    for(i = 0 ;i < 1024;i++)
    {
        writebuf[i] = i%256;
    }
    
    struct spi_ioc_transfer tr = {      //构建结构体变量
    .tx_buf = (unsigned long)writebuf,  //发送缓存
    .rx_buf = (unsigned long)readbuf,   //接收缓存
    .len = len,                         //读写长度
    .delay_usecs = 0,
    .speed_hz = 10000000,              //spi最大传输速率
    .bits_per_word = 8,                //spi字长
    };
    ret = ioctl(fd_spi, SPI_IOC_MESSAGE(1), &tr);//结构体变量传到内核，实现spi的边读边写
    if (ret < 0)
    {
        perror("can't send spi message");
        return ret;
    }
 
    for (i = 0; i<1024; i++) {
		if (!(i % 32))
		puts("");
		printf("%.2X ", readbuf[i]);  //打印读到的spi数据
	}
	puts("");
 
 
    return 0;
}

int main()
{
    spi_init();
    spi_write();
    //spi_read();
   //spi_write_read();
    return 0;
}